<template>
  <div class="register-form">
    <el-form
      ref="ruleFormRef"
      :label-width="70"
      :model="ruleForm"
      status-icon
      :rules="rules"
    >
      <el-form-item label="账号" prop="account">
        <el-input
          ref="accountRef"
          :maxlength="8"
          :disabled="isLoading"
          v-model="ruleForm.account"
          @keypress.enter.prevent="focus('passRef')"
          placeholder="请输入账号"
        />
        <SvgIcon popper-class="input-icon" icon-class="user" />
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input
          ref="passRef"
          type="password"
          v-model="ruleForm.password"
          placeholder="请输入密码"
          :disabled="isLoading"
          @keypress.enter.prevent="focus('checkPassRef')"
          :maxlength="10"
        />
        <SvgIcon popper-class="input-icon" icon-class="lock" />
      </el-form-item>
      <el-form-item label="重复密码" prop="repeatPass">
        <el-input
          ref="checkPassRef"
          type="password"
          v-model="ruleForm.repeatPass"
          placeholder="请再一次输入密码"
          @keypress.enter.prevent="focus('verCode')"
          :disabled="isLoading"
          :maxlength="10"
        />
        <SvgIcon popper-class="input-icon" icon-class="locked" />
      </el-form-item>
      <el-form-item label="验证码" prop="verCode">
        <el-input
          class="vercode"
          ref="verCode"
          placeholder="验证码"
          :maxlength="4"
          @keypress.enter.prevent="startRegister(ruleFormRef)"
          :disabled="isLoading"
          v-model="ruleForm.verCode"
        />
        <img :src="indexStore.codeUrl" alt="获取验证码失败" @click="refreshCode" />
      </el-form-item>
    </el-form>
  </div>
  <div class="register-footer">
    <el-button
      :disabled="isRequest || isLoading"
      type="primary"
      @click="startRegister(ruleFormRef)"
      :loading="isLoading"
      ><template #loading><Loading /></template
      >{{ isLoading ? "注册中" : "注册" }}</el-button
    >
    <div class="turn-login">
      <el-link :disabled="isRequest || isLoading" :underline="false" @click="turnPage"
        >已有账号？</el-link
      >
    </div>
  </div>
</template>

<script lang="ts">
export default defineComponent({
  methods: {
    // 输入框聚焦
    focus(refValue: string): void {
      (this.$refs as any)[refValue].focus();
    },
  },
  mounted() {
    (this.$refs.accountRef as any).focus();
  },
});
</script>

<script lang="ts" setup>
import { ref, reactive, defineComponent } from "vue";
import { useRouter } from "vue-router";
import LoadingBar from "@/plugins/loadingBar";
import { ElMessage } from "element-plus";
import type { FormInstance, ElInput } from "element-plus";
import axios from "axios";
import { Base64 } from "js-base64";
import { usePinia } from "@/pinia/index";

const loadingBar = new LoadingBar();
const router = useRouter();
const indexStore = usePinia();

const props = withDefaults(
  defineProps<{
    // 进入页面前背景图片请求和验证码请求是否结束
    isRequest?: boolean;
  }>(),
  {
    isRequest: false,
  }
);

// 跳转至注册页面
const turnPage = (() => {
  let isLoading: boolean = false;
  return () => {
    if (isLoading) return;
    isLoading = true;
    loadingBar.start();
    indexStore
      .getLoginBkImg()
      .then((code: number) => {
        if (code === 1) {
          loadingBar.finsh();
          router.push({ name: "login" });
        } else {
          loadingBar.unMount();
          ElMessage.error("加载失败");
        }
        isLoading = false;
      })
      .catch(() => {
        isLoading = false;
        loadingBar.unMount();
        ElMessage.error("加载失败");
      });
  };
})();

// 刷新验证码
const refreshCode = (() => {
  // 是否刷新完毕
  let isFinsh: boolean = true;
  return (): void => {
    if (!isFinsh || isLoading.value) return;
    isFinsh = false;
    indexStore
      .getVerCode()
      .then((code: number): void => {
        isFinsh = true;
        if (code === 0) ElMessage.error("刷新失败");
      })
      .catch(() => ElMessage.error("刷新失败"));
  };
})();

/**
 * 表单内的属性值
 */
const ruleForm = reactive<ValidateUser>({
  account: "",
  password: "",
  repeatPass: "",
  verCode: "",
});

// 给el-form标签一个ref属性
const ruleFormRef = ref<FormInstance>();

// 表单的验证
const validateInput = (
  title: string,
  count?: number
): ((rule: any, value: string, callback: any) => void) => (
  rule: any,
  value: string,
  callback: any
): void => {
  if (!value) callback(new Error(`${title}不能为空`));
  else if (!value.match(/^[a-zA-Z0-9_\\.]{1,}$/g) && title !== "验证码")
    callback(
      new Error(
        `${title === "重复密码" ? "密码" : title}只能由字母、数字、小数点和下划线组成`
      )
    );
  else if (count && value.length < count)
    callback(new Error(`${title === "重复密码" ? "密码" : title}长度不能少于${count}位`));
  else {
    let isRight: boolean = true;
    if (title === "密码" && ruleForm.repeatPass && ruleFormRef.value)
      ruleFormRef.value.validateField("repeatPass");
    if (title === "重复密码" && value !== ruleForm.password) {
      callback(new Error("两次密码输入不一致"));
      isRight = false;
    }
    if (isRight) callback();
  }
};
/**
 * 表单校验规则
 */
const rules = reactive({
  verCode: [{ validator: validateInput("验证码"), trigger: "blur" }],
  account: [{ validator: validateInput("账号", 8), trigger: "change" }],
  password: [{ validator: validateInput("密码", 10), trigger: "change" }],
  repeatPass: [{ validator: validateInput("重复密码", 10), trigger: "blur" }],
});

// 是否显示登录加载动画
const isLoading = ref<boolean>(false);
// 给账号输入框一个ref属性
const accountRef = ref<typeof ElInput>();

// 开始注册操作
const startRegister = (formEl: FormInstance | undefined) => {
  if (props.isRequest || !formEl) return;
  formEl.validate((valid) => {
    if (valid) {
      isLoading.value = true;
      axios
        .post("api/user/register", {
          data: Base64.encode(
            JSON.stringify({
              account: ruleForm.account,
              password: ruleForm.password,
              vercode: ruleForm.verCode,
              codeKey: sessionStorage.getItem("codeKey"),
            })
          ),
        })
        .then((res) => {
          isLoading.value = false;
          const { data } = res;
          if (data.code === 1) {
            ElMessage.success("注册成功");
            router.push({ name: "login" });
          } else {
            ElMessage.error(`${data.msg}`);
            (accountRef.value as any).focus();
            refreshCode();
          }
        })
        .catch(() => {
          isLoading.value = false;
          ElMessage.error("注册失败");
          (accountRef.value as any).focus();
          refreshCode();
        });
    }
  });
};
</script>

<style lang="scss" scoped>
.register {
  &-form {
    margin: 25px auto;
    width: 320px;

    .vercode {
      width: 95px;
      margin-right: 20px;

      :deep(.el-input__inner) {
        width: 85px;
        padding-left: 10px;
      }
    }

    :deep(.el-form-item) {
      margin-bottom: 23px;
    }

    :deep(.el-input__inner) {
      padding-left: 28px;
    }
  }

  &-footer {
    margin: 30px auto;
    width: 320px;

    :deep(.el-button) {
      width: 320px;
    }

    .turn-login {
      margin-top: 20px;
      text-align: right;
    }
  }
}
</style>
